/*
 * 版权所有 (C) 2015 知启蒙(ZHIQIM) 保留所有权利。[遇见知启蒙，邂逅框架梦，本文采用木兰宽松许可证第2版]
 * 
 * https://zhiqim.org/project/zhiqim_products/gitcan.htm
 *
 * gitcan is licensed under Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *          http://license.coscl.org.cn/MulanPSL2
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PSL v2 for more details.
 */
package org.zhiqim.gitcan.dao;

import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import org.zhiqim.gitcan.dbo.GitCalendar;
import org.zhiqim.gitcan.model.CalendarWeekModel;
import org.zhiqim.httpd.HttpRequest;
import org.zhiqim.kernel.util.DateTimes;
import org.zhiqim.orm.ORM;
import org.zhiqim.orm.ORMException;
import org.zhiqim.orm.dbo.Selector;

/**
 * 日历数据访问对象
 *
 * @version v1.0.0 @author zouzhigang 2017-11-8 新建与整理
 */
public class GitCalendarDao
{
    /**
     * 获取指定年月的星期表，包括跨月的星期
     * 
     * @param request       请求对象
     * @param year          年份，格式如2017
     * @param month         月份，格式如08
     * @return              星期列表
     * @throws SQLException 数据库SQL异常
     * @throws ORMException 数据库ORM异常
     */
    public static List<CalendarWeekModel> getCalendarWeekList(HttpRequest request, int year, int month) throws SQLException, ORMException
    {
        //1.查出上个月，当前月和下个月的个人计划总结和日历表
        int prevYear = month==1?year-1:year;
        int prevMonth = month==1?12:month-1;
        
        int nextYear = month==12?year+1:year;
        int nextMonth = month==12?1:month+1;
        
        Selector selector = new Selector();
        selector.addMustThenG("calendarDate", prevYear * 10000 + prevMonth * 100);
        selector.addMustThenL("calendarDate", nextYear * 10000 + (nextMonth+1) * 100);
        List<GitCalendar> calendarList = ORM.table().list(GitCalendar.class, selector);
        
        //2.从当前年月1号，向前找到有效周起始日
        int prevDate = year * 10000 + month * 100 + 1;
        while (true)
        {
            if (isCalendarRest(calendarList, prevDate))
            {//找到一天是休息日即结束，暂不处理极限的整个月都是工作日的情况
                break;
            }
            
            prevDate = DateTimes.getPreviousDateInt(prevDate);
        }
        
        int firstDate = DateTimes.getNextDateInt(prevDate);
        
        //3.从当前年月最后一天，向后找到有效周结束日
        int maxDays = DateTimes.getMonthDays(year, month);
        int nextDate = year * 10000 + month * 100 + maxDays;
        while (true)
        {
            if (isCalendarRest(calendarList, nextDate))
            {//找到一天是休息日即结束，暂不处理极限的整个月都是工作日的情况
                break;
            }
            
            nextDate = DateTimes.getNextDateInt(nextDate);
        }
        
        int lastDate = DateTimes.getPreviousDateInt(nextDate);
        
        //4.从firstDate到lastDate之间的周表计算出来
        List<CalendarWeekModel> weekList = new ArrayList<>();
        CalendarWeekModel keyModel = null;
        for (int date=firstDate;date<=lastDate;date=DateTimes.getNextDateInt(date))
        {
            if (isCalendarRest(calendarList, date))
            {//休息日
                if (keyModel != null)
                {//增加到列表中
                    keyModel.setEndDate(DateTimes.getPreviousDateInt(date));
                    weekList.add(keyModel);
                    keyModel = null;
                }
            }
            else
            {//工作日
                if (keyModel == null)
                {
                    keyModel = new CalendarWeekModel(date);
                }
            }
        }
        
        if (keyModel != null)
        {//最后一周
            keyModel.setEndDate(lastDate);
            weekList.add(keyModel);
            keyModel = null;
        }
        
        return weekList;
    }
    
    /************************************************************************************/
    //从日历列表中判断是否为休息日
    /************************************************************************************/
    
    private static boolean isCalendarRest(List<GitCalendar> calendarList, int date)
    {
        GitCalendar calendar = getCalendar(calendarList, date);
        if (calendar != null)
            return calendar.isCalendarRest();
        
        //没有配置，取周末为休息日
        return DateTimes.getDateWeek7(date) >= 6;
    }
    
    private static GitCalendar getCalendar(List<GitCalendar> calendarList, int date)
    {
        for (GitCalendar item : calendarList)
        {
            if (item.getCalendarDate() == date)
                return item;
        }
        
        return null;
    }
}
